package hichecker.ui.general_views.container_panel.navigation;

import hichecker.controller.Config;
import hichecker.controller.MainController;
import hichecker.tools.event.HiCheckerEvent;
import hichecker.tools.event.abstract_event.Observable;
import hichecker.tools.event.abstract_event.Observer;
import hichecker.ui.components.icon_factory.IconFactory;
import hichecker.ui.components.icon_factory.IconFactory.IconType;
import hichecker.ui.general_views.container_panel.ContainerPanel;
import hichecker.ui.general_views.container_panel.content.ContentPanel;
import hichecker.university.UniversityPart;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class NavigationPanel extends JPanel implements Observer<HiCheckerEvent>{
	private MainController controller;
	private ContainerPanel container;

	private UniversityPart item;
	private JList list;
	private DefaultListModel listModel;
	private UUID selectedID = null;

	public NavigationPanel(final UniversityPart item, final ContainerPanel container,
			final MainController controller) {
		this.container = container;
		this.controller = controller;
		this.item = item;

		// Observer
		controller.addObserver(this);

		// ListModel
		listModel = new DefaultListModel();

		// List
		list = new JList(listModel);
		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		list.setCellRenderer(new NavigationCellRenderer());
		list.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				setContent(list.getSelectedIndex(), item);
			}
		});
		list.setPreferredSize(new Dimension(140, 0));
		list.setMinimumSize(new Dimension(0, 0));

		List<JButton> addButtons = new ArrayList<JButton>();
		String toolTip = "";
		for (int i = 0; i < item.getPossibleSubPart().length; i++) {
			UniversityPart subPart = item.getPossibleSubPart()[i];
			final int index = i;
			JButton button = IconFactory.getIconButton(null, subPart.getName() + " " + Config.MENU_ADD, subPart.getAddIcon(), new AbstractAction() {
				@Override
				public void actionPerformed(ActionEvent e) {
					controller.addSubItem(index, item);
				}
			});
			addButtons.add(button);
			toolTip += subPart.getName() + "/";
		}


		// cut last "/" from tooltip text
		toolTip = toolTip.substring(0, toolTip.length() - 1) + " ";

		// RemoveButton
		JButton removeButton = IconFactory.getIconButton(null, toolTip + Config.MENU_REMOVE,
				IconType.REMOVE, new AbstractAction() {
					@Override
					public void actionPerformed(ActionEvent e) {
						if (!isContentCorrect())
							return;
						removeSubItem(list.getSelectedIndex());
					}
				});

		// ButtonToolBar
		JToolBar buttonBar = new JToolBar();
		buttonBar.setFloatable(false);
		buttonBar.add(Box.createHorizontalGlue());
		for (JButton button : addButtons)
			buttonBar.add(button);
		buttonBar.add(removeButton);

		// Layout
		setLayout(new BorderLayout());
		add(list, BorderLayout.CENTER);
		add(buttonBar, BorderLayout.SOUTH);

		// Content
		fillList();
	}

	private void fillList() {
		fillList(null);
	}

	private void fillList(UUID eventID) {
		listModel.removeAllElements();
		listModel.addElement(item);
		for (UniversityPart subItem : item.getSubParts()) {
			listModel.addElement(subItem);
		}

		// Possible indices
		int index;
		int menuIndex = getListIndex(eventID);
		int selectedIndex = getListIndex(selectedID);

		// Get first index unequal -1
		if (menuIndex == -1)
			if (selectedIndex == -1)
				index = 0;
			else
				index = selectedIndex;
		else
			index = menuIndex;

		// set listindex
		list.setSelectedIndex(index);
	}

	private int getListIndex(UUID id) {
		for (int i = 0; i < listModel.getSize(); i++) {
			UniversityPart part = (UniversityPart) listModel.get(i);
			if (part.getID() == id) {
				return i;
			}
		}
		return -1;
	}

	private void setContent(int index, UniversityPart item) {
		// no element selected, nothing changed
		int oldIndex = getListIndex(selectedID);
		if (index == -1 || oldIndex == index || !isContentCorrect())
			return;

		// Selected element
		UniversityPart selectedItem = (UniversityPart) listModel.getElementAt(index);

		// Remember current id
		selectedID = selectedItem.getID();

		// Define new sub content
		ContentPanel subContent;

		// Element is root element
		boolean showConfig = controller.isShowConfig();
		if (selectedItem.getClass() == item.getClass()) {
			subContent = item.getRepresentation(showConfig, controller);
			// Element is element at last level
		} else if (selectedItem.getSubParts() == null) {
			subContent = selectedItem.getRepresentation(showConfig, controller);
			// Element is sub element
		} else {
			subContent = new ContainerPanel(selectedItem, controller);
		}

		// Show element
		container.setContent(subContent);
	}

	private void removeSubItem(int index) {
		// security question
		int answer = JOptionPane.showConfirmDialog(NavigationPanel.this,
				Config.MENU_CONFIRM_DELETE_DIALOG, Config.MENU_CONFIRM_DELETE_HEADER,
				JOptionPane.YES_NO_OPTION);
		if (answer != JOptionPane.YES_OPTION)
			return;

		// Only sub item
		if (index < 1)
			return;

		// Remove sub item
		UniversityPart subItem = (UniversityPart) listModel.get(index);
		controller.removeSubItem(subItem.getID(), item);
	}

	private boolean isContentCorrect() {
		ContentPanel content = container.getContent();
		if (content != null && !content.isCorrect()) {
			JOptionPane.showMessageDialog(NavigationPanel.this,
					"Bitte überprüfen Sie ihre aktuellen Eingaben, bevor Sie fortfahren.",
					"Eingaben nicht korrekt!", JOptionPane.WARNING_MESSAGE);
			list.setSelectedIndex(getListIndex(selectedID));
			return false;
		}
		return true;
	}

	@Override
	public void notify(Observable<? extends HiCheckerEvent> sender, HiCheckerEvent event) {
		switch (event.getEventType()) {
		// Menu structure changed
		case NEW_MENU_CONTENT:
			// Evaluate event if eventItem equals item
			UniversityPart eventItem = event.getItem();
			if (eventItem.getClass() == item.getClass()) {
				// refill list
				fillList(event.getNewItemID());
				break;
			}
			// category name changes
		case UPDATE_ITEM_NAME:
			// Change categorie name
			listModel.set(0, item);
			break;
		}
	}
}
